package de.ipk_gatersleben.bit.bi.edal.publication.metadata;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.rmi.RemoteException;
import javax.mail.internet.InternetAddress;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import de.ipk_gatersleben.bit.bi.edal.primary_data.file.EdalException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataDirectoryException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataEntityException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataEntityVersionException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PublicReferenceException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.EnumDublinCoreElements;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.MetaData;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.MetaDataException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.reference.PersistentIdentifier;
import de.ipk_gatersleben.bit.bi.edal.publication.DateTimePicker;
import de.ipk_gatersleben.bit.bi.edal.publication.PropertyLoader;
import de.ipk_gatersleben.bit.bi.edal.publication.PublicationButtonLinePanel;
import de.ipk_gatersleben.bit.bi.edal.publication.PublicationModul;
import de.ipk_gatersleben.bit.bi.edal.publication.PublicationVeloCityCreater;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientPrimaryDataDirectory;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientPrimaryDataEntity;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientPrimaryDataFile;

public class ProgressSwingWorker extends SwingWorker<Object, Object> {

	private JProgressBar overallProgressBar;
	private JProgressBar fileProgressBar;
	private JButton sendButton;
	private JButton cancelButton;
	private JEditorPane htmlPanel;

	private final Path files;
	private MetaData metaData;
	private ClientPrimaryDataDirectory userDirectory;
	private InternetAddress loggedUser;
	private DateTimePicker picker;

	public ProgressSwingWorker(JProgressBar overAllProgressBar,
			JProgressBar fileProgressBar, JButton sendButton,
			JButton cancelButton, JEditorPane htmlPanel, Path files,
			MetaData metaData, ClientPrimaryDataDirectory userDirectory,
			InternetAddress loggedUser, DateTimePicker picker) {

		this.overallProgressBar = overAllProgressBar;
		this.fileProgressBar = fileProgressBar;
		this.sendButton = sendButton;
		this.cancelButton = cancelButton;
		this.htmlPanel = htmlPanel;
		this.files = files;
		this.metaData = metaData;
		this.userDirectory = userDirectory;
		this.loggedUser = loggedUser;
		this.picker = picker;
	}

	private void publishDirectory(ClientPrimaryDataDirectory directory) {
		try {
			directory.switchCurrentVersion(directory.getCurrentVersion());
			directory.addPublicReference(PersistentIdentifier.DOI);

			if (this.picker.getCalendar() != null) {
				directory.getCurrentVersion().setAllReferencesPublic(
						this.loggedUser, this.picker.getCalendar());

			} else {
				directory.getCurrentVersion().setAllReferencesPublic(
						this.loggedUser, null);
			}
		} catch (RemoteException | PrimaryDataEntityException
				| PublicReferenceException | PrimaryDataEntityVersionException e) {
			e.printStackTrace();
		}
	}

	@Override
	protected Object doInBackground() throws Exception {
		storeFiles();
		return null;
	}

	@Override
	protected void done() {

		try {
			this.htmlPanel.setText(PublicationVeloCityCreater
					.generateFinishUploadPage());
		} catch (EdalException e) {
			e.printStackTrace();
		}

		((ProgressBarDialog) SwingUtilities.getRoot(this.sendButton))
				.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

		this.sendButton.setEnabled(true);
		this.sendButton.setText("Publish another data set");
		this.cancelButton.setEnabled(true);
		this.cancelButton.setText("Quit");

		this.sendButton.removeActionListener(this.sendButton
				.getActionListeners()[0]);
		this.sendButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent actionEvent) {

				if (actionEvent.getSource().equals(sendButton)) {
					SwingUtilities.getWindowAncestor(sendButton).dispose();
				}

			}
		});

		this.cancelButton.removeActionListener(this.cancelButton
				.getActionListeners()[0]);
		this.cancelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				int result = JOptionPane.showConfirmDialog(
						PublicationModul.getFrame(), "Close "
								+ PropertyLoader.PROGRAM_NAME + " ?", "EXIT",
						JOptionPane.YES_NO_OPTION);
				if (result == JOptionPane.YES_OPTION) {
					System.exit(0);
				}

			}
		});
	}

	private void storeFiles() {

		if (Files.isDirectory(this.files)) {

			try {

				// this.metaData.setElementValue(EnumDublinCoreElements.TITLE,
				// metaData.getElementValue(EnumDublinCoreElements.TITLE));

				PublicationDirectoryVisitorRmi2 edalVisitor = new PublicationDirectoryVisitorRmi2(
						this.overallProgressBar, this.fileProgressBar,
						this.userDirectory, this.files, this.metaData,
						PublicationButtonLinePanel.updatePublicationFlag);

				Files.walkFileTree(this.files, edalVisitor);

				this.fileProgressBar
						.setValue(this.fileProgressBar.getMaximum());
				this.fileProgressBar.setString("100%");
				this.overallProgressBar.setValue(this.overallProgressBar
						.getMaximum());
				this.overallProgressBar.setString("100%");

				publishDirectory(edalVisitor.getRootDirectoryToPublish());

			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		else {

			if (PublicationButtonLinePanel.updatePublicationFlag) {

				/* get existing directory by TITLE */
				ClientPrimaryDataDirectory directory = null;
				try {

					directory = (ClientPrimaryDataDirectory) this.userDirectory
							.getPrimaryDataEntity(metaData.getElementValue(
									EnumDublinCoreElements.TITLE).toString());

					setNewMetaData(directory, metaData);

					directory.switchCurrentVersion(directory
							.getCurrentVersion());

				} catch (RemoteException | PrimaryDataDirectoryException
						| MetaDataException | PrimaryDataEntityVersionException e) {
					e.printStackTrace();
				}

				/* create new file or get existing on */
				ClientPrimaryDataFile file = null;

				try {
					if (directory.exist(this.files.toFile().getName())) {
						file = (ClientPrimaryDataFile) directory
								.getPrimaryDataEntity(this.files.toFile()
										.getName());

					} else {
						file = directory.createPrimaryDataFile(this.files
								.toFile().getName());
					}
				} catch (RemoteException | PrimaryDataDirectoryException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

				setNewMetaData(file, metaData);

				FileStoreSwingWorker worker = new FileStoreSwingWorker(
						this.fileProgressBar, this.files, file);

				worker.execute();

				this.fileProgressBar.setString("100%");
				this.fileProgressBar.setValue(100);

				this.overallProgressBar.setValue(this.overallProgressBar
						.getValue() + 1);

				publishDirectory(directory);
			}

			else {
				try {
					ClientPrimaryDataDirectory directory = this.userDirectory
							.createPrimaryDataDirectory(metaData
									.getElementValue(
											EnumDublinCoreElements.TITLE)
									.toString());

					setNewMetaData(directory, metaData);

					final ClientPrimaryDataFile clientPrimaryDataFile = directory
							.createPrimaryDataFile(this.files.toFile()
									.getName());

					FileStoreSwingWorker worker = new FileStoreSwingWorker(
							this.fileProgressBar, this.files,
							clientPrimaryDataFile);

					worker.execute();

					this.fileProgressBar.setString("100%");
					this.fileProgressBar.setValue(100);

					this.overallProgressBar.setValue(this.overallProgressBar
							.getValue() + 1);

					publishDirectory(directory);
				} catch (RemoteException | PrimaryDataDirectoryException

				| MetaDataException e) {
					e.printStackTrace();
				}
			}

		}
	}

	private void setNewMetaData(
			ClientPrimaryDataEntity clientPrimaryDataEntity,
			MetaData newMetaData) {
		try {
			MetaData metaData = clientPrimaryDataEntity.getMetaData().clone();

			metaData.setElementValue(EnumDublinCoreElements.CREATOR,
					newMetaData.getElementValue(EnumDublinCoreElements.CREATOR));
			metaData.setElementValue(
					EnumDublinCoreElements.CONTRIBUTOR,
					newMetaData
							.getElementValue(EnumDublinCoreElements.CONTRIBUTOR));
			metaData.setElementValue(EnumDublinCoreElements.SUBJECT,
					newMetaData.getElementValue(EnumDublinCoreElements.SUBJECT));
			metaData.setElementValue(EnumDublinCoreElements.LANGUAGE,
					newMetaData
							.getElementValue(EnumDublinCoreElements.LANGUAGE));
			metaData.setElementValue(
					EnumDublinCoreElements.DESCRIPTION,
					newMetaData
							.getElementValue(EnumDublinCoreElements.DESCRIPTION));
			metaData.setElementValue(EnumDublinCoreElements.PUBLISHER,
					newMetaData
							.getElementValue(EnumDublinCoreElements.PUBLISHER));

			clientPrimaryDataEntity.setMetaData(metaData);

		} catch (RemoteException | CloneNotSupportedException
				| PrimaryDataEntityVersionException | MetaDataException e) {
			e.printStackTrace();
		}

	}

}
